import os
import platform
import sys
from datetime import datetime, date, time # Import date specifically for clarity and date operations
import struct
import win32evtlogutil
import win32evtlog
import pywintypes

# --- Windows-specific imports ---
if platform.system() == "Windows":
    try:
        import win32evtlog
        import win32evtlogutil
        import pywintypes
    except ImportError:
        print("错误：缺少 'pywin32' 库。")
        print("请在命令行运行 'pip install pywin32' 进行安装。")
        sys.exit(1)

def get_user_date():
    """提示用户输入日期并验证格式"""
    while True:
        date_str = input("请输入您想查询的日期 (格式:YYYY-MM-DD): ")
        try:
            # Corrected: Use datetime.strptime directly
            target_date = datetime.strptime(date_str, "%Y-%m-%d").date()
            return target_date
        except ValueError:
            print("日期格式错误，请输入YYYY-MM-DD 格式，例如 2023-10-27")

def get_file_activity(target_date):
    """
    扫描用户主目录下的文件活动。
    注意：这可能需要一些时间。
    """
    print("\n--- [1/2] 正在扫描文件活动 (这可能需要几分钟) ---")

    search_paths = [os.path.expanduser('~')]

    created_files = []
    modified_files = []

    for path in search_paths:
        print(f"正在扫描: {path} ...")
        if not os.path.exists(path):
            print(f"警告：目录 {path} 不存在，已跳过。")
            continue
        try:
            for root, dirs, files in os.walk(path):
                dirs[:] = [d for d in dirs if not d.startswith('.') and 'AppData' not in root]
                for file in files:
                    try:
                        filepath = os.path.join(root, file)
                        stat = os.stat(filepath)

                        # Corrected: Use datetime.fromtimestamp directly
                        m_time = datetime.fromtimestamp(stat.st_mtime).date()
                        if m_time == target_date:
                            modified_files.append((datetime.fromtimestamp(stat.st_mtime), filepath))

                        # Corrected: Use datetime.fromtimestamp directly
                        c_time = datetime.fromtimestamp(stat.st_ctime).date()
                        if c_time == target_date:
                            created_files.append((datetime.fromtimestamp(stat.st_ctime), filepath))

                    except (FileNotFoundError, PermissionError):
                        continue
        except PermissionError:
            print(f"警告：没有权限访问目录 {path}，已跳过。")


    print("\n--- 文件活动结果 ---")
    if not created_files and not modified_files:
        print("在指定日期内，未在扫描目录中找到任何文件创建或修改活动。")
    else:
        if created_files:
            print(f"\n[+] 在 {target_date} 创建的文件:")
            created_files.sort()
            for ts, path in created_files:
                print(f"  {ts.strftime('%H:%M:%S')} - {path}")

        if modified_files:
            print(f"\n[*] 在 {target_date} 修改的文件:")
            modified_files.sort()
            for ts, path in modified_files:
                print(f"  {ts.strftime('%H:%M:%S')} - {path}")


def get_windows_events(target_date):
    """
    从Windows事件日志中获取软件运行和系统事件。
    需要管理员权限才能访问安全日志。
    """
    print("\n--- [2/2] 正在查询Windows事件日志 ---")
    log_types = ['Application', 'System', 'Security']

    all_events = []
    processed_count = 0
    # 为倒序查询设置一个较大的初始值，防止无限循环
    max_events_to_read = 100000

    for log_type in log_types:
        try:
            hand = win32evtlog.OpenEventLog(None, log_type)
            flags = win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ

            # 重置计数器
            processed_count = 0

            while processed_count < max_events_to_read:
                events = win32evtlog.ReadEventLog(hand, flags, 0)
                if not events:
                    break

                processed_count += len(events)

                stop_reading = False
                for event in events:
                    # Ensure event.TimeGenerated is converted to date for comparison
                    event_time = event.TimeGenerated.date()

                    if event_time < target_date:
                        stop_reading = True
                        break

                    if event_time == target_date:
                        event_data = {
                            "time": event.TimeGenerated,
                            "source": event.SourceName,
                            "id": event.EventID & 0xFFFF,
                            "type": event.EventType,
                            "message": str(win32evtlogutil.SafeFormatMessage(event, log_type))
                        }
                        all_events.append(event_data)

                if stop_reading:
                    break

            win32evtlog.CloseEventLog(hand)

        except pywintypes.error as e:
            if e.winerror == 5:
                print(f"警告：访问 '{log_type}' 日志被拒绝。请尝试“以管理员身份运行”此脚本以获取完整信息。")
            else:
                print(f"读取 '{log_type}' 日志时出错: {e}")

    print("\n--- 系统事件和软件运行结果 ---")
    if not all_events:
        print("在指定日期内，未找到任何系统事件或软件运行记录。")
    else:
        all_events.sort(key=lambda x: x['time'])

        for event in all_events:
            # Event ID 4688 is for Process Creation (requires audit policy enabled)
            if event['source'] == 'Microsoft-Windows-Security-Auditing' and event['id'] == 4688:
                process_name = "未知进程"
                for line in event['message'].splitlines():
                    if '新进程名称' in line or 'New Process Name' in line:
                        # Extract the process name from the message details
                        process_name = line.split(':')[-1].strip()
                        break
                print(f"[+] {event['time'].strftime('%H:%M:%S')} - 软件运行: {process_name} (事件ID: {event['id']})")
            else:
                # Print other important system events (Error or Warning types)
                if event['type'] in [1, 2]: # 1=Error, 2=Warning
                    # Handle cases where message might be empty or just whitespace
                    if event['message'] and event['message'].strip():
                        first_line = event['message'].splitlines()[0]
                    else:
                        first_line = "[无具体消息内容]" # Provide a placeholder for empty messages

                    print(f"[*] {event['time'].strftime('%H:%M:%S')} - 系统事件: {event['source']} (ID: {event['id']}) - {first_line}")


def format_timestamp(timestamp):
    return timestamp.strftime("%Y-%m-%d %H:%M:%S")


def get_lnk_files_for_day(target_date):
    """
    扫描用户桌面、最近文档等位置的.lnk文件，获取其时间戳。
    LNK文件解析也比较复杂，这里只检查文件本身的修改时间。
    """
    print(f"\n--- 正在扫描 {target_date.strftime('%Y-%m-%d')} 的快捷方式文件 (.lnk) ---")
    lnk_paths = [
        os.path.expanduser("~/Desktop"),
        os.path.expanduser("~/Documents"),
        os.path.expanduser("~/AppData/Roaming/Microsoft/Windows/Recent"), # 最近使用的项目
    ]

    lnk_found = 0
    for path in lnk_paths:
        if not os.path.exists(path):
            print(f"DEBUG: LNK路径不存在或无法访问: {path}") # Debug print
            continue
        for root, _, files in os.walk(path):
            for file in files:
                if file.lower().endswith(".lnk"):
                    lnk_file_path = os.path.join(root, file)
                    try:
                        mtime_datetime = datetime.fromtimestamp(os.path.getmtime(lnk_file_path))
                        mtime_date = mtime_datetime.date()

                        # Debug prints for comparison
                        # print(f"DEBUG: Checking {lnk_file_path}")
                        # print(f"DEBUG: File mtime_date: {mtime_date}, Target date: {target_date}")
                        # print(f"DEBUG: Match? {mtime_date == target_date}")

                        if mtime_date == target_date: # target_date is already a date object
                            print(f"    LNK文件: {lnk_file_path}, 最后修改时间: {format_timestamp(mtime_datetime)}")
                            lnk_found += 1
                    except Exception as e:
                        # print(f"DEBUG: Error processing LNK file {lnk_file_path}: {e}") # Enable for detailed errors
                        pass # 忽略错误
    print(f"--- 找到 {lnk_found} 个 {target_date.strftime('%Y-%m-%d')} 相关快捷方式文件 ---")

# ... (rest of the code, including main function, remains the same) ...
def main():
    """主程序入口"""
    print("--- Windows 日常活动取证工具 ---")

    # 检查是否有命令行参数
    if len(sys.argv) < 2:
        print("用法: python your_script_name.py YYYY-MM-DD")
        print("例如: python activity_monitor.py 2024-06-19")
        sys.exit(1) # 退出程序，表示错误

    date_str = sys.argv[1] # 获取第一个命令行参数作为日期字符串

    try:
        # Corrected: Use datetime.strptime directly
        target_date = datetime.strptime(date_str, "%Y-%m-%d").date() # Convert to date object
    except ValueError:
        print(f"错误: 日期格式不正确。请使用 YYYY-MM-DD 格式。您输入的是: {date_str}")
        sys.exit(1) # 退出程序，表示错误

    print(f"\n正在查询 {target_date.strftime('%Y年%m月%d日')} 的计算机活动...")

    get_file_activity(target_date)
    get_windows_events(target_date)
    get_lnk_files_for_day(target_date)


    print("\n==============================================")
    print("查询完成。")
    print("提示：软件运行记录依赖于系统安全审核策略是否开启。")
    print("文件扫描范围仅限于用户主目录，您可以修改代码以扫描更多位置。")
    print("==============================================")


if __name__ == "__main__":
    main()